//
//  dCurveView.m
//  Accuro Care
//
//  Created by Yongfeng Li on 6/30/14.
//  Copyright (c) 2014 Yongfeng Li. All rights reserved.
//

#import "AppDelegate.h"
#import "UiCurveView.h"
#import "H_RateItem.h"

#define NLSystemVersionGreaterOrEqualThan(version)  ([[[UIDevice currentDevice] systemVersion] floatValue] >= version)
#define IOS7_OR_LATER   NLSystemVersionGreaterOrEqualThan(7.0)
#define GraphColor      [[UIColor whiteColor] colorWithAlphaComponent:0.75]
#define str(index)      [NSString stringWithFormat : @"%.0f", ([[self.values objectAtIndex:(index)] floatValue] + _yAvgVal)]
#define point(x, y)     CGPointMake((x) * kXScale, yOffset + (y) * kYScale)

#define _nBarCount _nDurtBarNumber
#define _nExtBarCount 1

#define topMargin 15 //not used
#define leftMargin 50
#define rightMaring 2
#define _nBottomMargin 34;

//bar
#define DEGREES_TO_RADIANS(x) (M_PI * x / 180.0)

const CGFloat   kXSpan = 5.0;
const CGFloat   kYScale = 2.0;
CGFloat kXScale = 1.0;

static int _nMoveCurveTick = 0;

//static BOOL _bRedraw = NO;

static inline CGAffineTransform
CGAffineTransformMakeScaleTranslate(CGFloat sx, CGFloat sy, CGFloat dx, CGFloat dy)
{
    return CGAffineTransformMake(sx, 0.f, 0.f, sy, dx, dy);
}

@implementation UICurveView {
    //BOOL _bDrawBgkd;
    UIColor* _barColor[_nBarCount+1];
    
  CGFloat _fFitHRMax;
  CGFloat _yMaxLine;
  CGFloat _yMinLine;
  CGFloat _yMin;
  CGFloat _yAvgVal;
  
  BOOL _bResetData;
  
  short _nTopBpmVal;
    
  float _fMinHRVal;
  float _fMaxHRVal;
    
  BOOL _bHorBar;
  BOOL _bIpad;
  BOOL _bIp6p;
  BOOL _bIp6;
  BOOL _bIp4s;
  BOOL _bBigScreen;
    
    // Bars
  __weak id <CurveViewDataSource> _dataSource;
  __weak id <CurveViewDelegate> _delegate;
    
  CALayer *_barLayer;
  CALayer *_borderLayer;
  //CAShapeLayer *_borderPathLayer;
    
  NSMutableArray* _barPathLayers;
  NSMutableArray* _barHeights;
  NSMutableArray* _barHoriPos;
  NSMutableArray* _hrtHeights;
    
  double _barHeightRatio;
  double _barWidthRatio;

    
  CGFloat _rightValue;
  NSInteger _topValue;
  NSInteger _numberOfBars;
    
  CALayer* _gridLayer;
    
  NSMutableArray *_barLabels;
  NSMutableArray *_barTexts;
    
  NSNumber *_maxHeight;
  NSNumber *_minHeight;
  NSNumber *_maxWidth;
  NSNumber *_minWidth;
  CGFloat _xLabelMaxHeight;
    
  UIView *_yLabelView;
  UIView *_xLabelView;
  CGFloat _xLabelRotation;
    
  UIView *_barTextView;

  CGFloat _afDurTime[_nBarCount];
  
  NSString* _sTimeDur[_nBarCount];
  NSString* _sMeasTime[16];
  int _nCurtColorIdx;
    
  BOOL _bMovrCurve;;
  BOOL _bViewDataRcd;
  CGFloat _fBottomMargin;
  
  int _nXaxisCount;
  
  CGFloat _fMaxDurVal;
  
  float _afPointCoef[_nBarCount];
  
  NSString* _asZoneTxt[_nBarCount+1];
}

@synthesize bViewDataRcd = _bViewDataRcd;
@synthesize m_yMin = _yMin;
@synthesize m_yMax = _yMaxLine;
@synthesize m_fMaxDurVal = _fMaxDurVal;

- (id)initWithFrame:(CGRect)frame hBar:(BOOL)bHorBar;
{
  _bIpad = NO;
  _bIp6p = NO;
  _bIp6 = NO;
  
  _bIp4s = NO;
  _bHorBar = bHorBar;
  _nTopBpmVal = 0;
    
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        [self initialize:frame.size.width hgt:frame.size.height];
        //self.backgroundColor = [[UIColor orangeColor] colorWithAlphaComponent:0.5];
        //self.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.25];
        self.backgroundColor = [UIColor clearColor];
        
        //_barColor[0] = [[UIColor grayColor] colorWithAlphaComponent:0.5];
        /*_barColor[0] = [[UIColor blueColor] colorWithAlphaComponent:0.5];
        _barColor[1] = [[UIColor blueColor] colorWithAlphaComponent:0.5];
        _barColor[2] = [[UIColor greenColor] colorWithAlphaComponent:0.5];
        _barColor[3] = [[UIColor yellowColor]colorWithAlphaComponent:0.5];
        _barColor[4] = [[UIColor orangeColor] colorWithAlphaComponent:0.5];
        _barColor[5] = [[UIColor redColor] colorWithAlphaComponent:0.5];*/
      
      _barColor[0] = [UIColor colorWithRed:213.0/255 green:48.0/255 blue:147.0/255 alpha:1.0];
      _barColor[1] = [UIColor colorWithRed:213.0/255 green:48.0/255 blue:147.0/255 alpha:1.0];
      _barColor[2] = [UIColor colorWithRed:246.0/255 green:230.0/255 blue:101.0/255 alpha:1.0];
      _barColor[3] = [UIColor colorWithRed:95.0/255 green:218.0/255 blue:83.0/255 alpha:1.0];
      _barColor[4] = [UIColor colorWithRed:53.0/255 green:182.0/255 blue:229.0/255 alpha:1.0];
      _barColor[5] = [UIColor colorWithRed:198.0/255 green:150.0/255 blue:215.0/255 alpha:1.0];
      //_barColor[5] = [UIColor colorWithRed:198.0/255 green:150.0/255 blue:215.0/255 alpha:1.0];
      
      for(int i=0; i<=_nBarCount; i++) {
        _sTimeDur[i] = @"0.00";
      }
        /*_sTimeDur[0] = @"0.0";
        _sTimeDur[1] = @"0.0";
        _sTimeDur[2] = @"0.0";
        _sTimeDur[3] = @"0.0";
        _sTimeDur[4] = @"0.0";
        _sTimeDur[5] = @"0.0";*/
    }
    if(!bHorBar) {
      [self initBarCtrls];
      for(int i=0; i<_nDurtBarNumber; i++) {
        _afPointCoef[i] = 1 + i;
      }
    }
    //_bDrawBgkd = NO;
    _bMovrCurve = NO;
    
    _nCurtColorIdx = 0;
    _bViewDataRcd = NO;
    
    _numberOfBars = [_dataSource numberOfBarsInBarChart:self];
  
  _bResetData = NO;
  
  _asZoneTxt[0] = @"";//@"EASY";
  _asZoneTxt[1] = @""; //@"LIGHT";
  _asZoneTxt[2] = @"";//@"MODERATE";
  _asZoneTxt[3] = @"";//@"INTENSE";
  _asZoneTxt[4] = @"";//@"VIGOROUS";
  
  return self;
}

- (void) initialize:(CGFloat)W hgt:(CGFloat)H
{
  kXScale = H * kYScale / W;
  [self setContentMode:UIViewContentModeRight];
  _values = [NSMutableArray array];
    
  _yMaxLine = 180;
  _yMinLine = 120;
  _yMin = 60;
  _yAvgVal = (_yMaxLine + _yMin) / 2;
    
  _fMinHRVal = _yMin;
  _fMaxHRVal = _yMaxLine;
  _fBottomMargin = _nBottomMargin;
  if(W < 700)
    _fBottomMargin /= 1.6;
  if(!_bHorBar)
    _fBottomMargin = 0;
    
  _bIpad = _bHorBar? H > 365: H > 243;
  if(!_bIpad) {
    _bIp6p = _bHorBar? H >= 230: H >= 115;
    if(!_bIp6p) {
      _bIp6 = _bHorBar? H > 208: H > 104;
      if(!_bIp6)
        _bIp4s = _bHorBar? (H < 134) : (H < 78);
    }
  }
  _bBigScreen = _bHorBar? H > 208: H > 104;
    //_nXaxisCount = _bIpad? 8: 7;
  _nXaxisCount = _bIpad? 10: 5;
    
  for(int i=0; i<_nBarCount; i++) {
  
  }
        
    
   /* __weak id   weakSelf = self;
    double      delayInSeconds = 2.0; //0.25;
    self.timer =
    dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
                           dispatch_get_main_queue());
    dispatch_source_set_timer(
                              _timer, dispatch_walltime(NULL, 0),
                              (unsigned)(delayInSeconds * NSEC_PER_SEC), 0);
    dispatch_source_set_event_handler(_timer, ^{
        [weakSelf updateValues];
    });
    dispatch_resume(_timer);*/
}

- (void) initBarCtrls
{
    _topValue = 10;
    
    _gridLayer = [CALayer layer];
    [self.layer addSublayer:_gridLayer];
    
    _barLayer = [CALayer layer];
    [self.layer addSublayer:_barLayer];
    
    _barPathLayers			= [[NSMutableArray alloc] init];
    _barHeights				= [[NSMutableArray alloc] init];
    _barHoriPos				= [[NSMutableArray alloc] init];
    _barLabels				= [[NSMutableArray alloc] init];
    _barTexts				= [[NSMutableArray alloc] init];
    
    self.animationDuration = 0.2f;
    self.hasGrids = YES;
    
    self.incrementValue = 100;
    self.incrmtxposValue = 10;
    self.barWidth = (self.frame.size.width / (_nBarCount+1)) - 1.25;
    //self.barAlpha = 1.0;
    //self.chartBorderColor = [UIColor blackColor];
    self.gridColor = [UIColor grayColor];
    self.hasYLabels = YES; //YES
    self.yLabelFont = [UIFont fontWithName:@"Helvetica" size:12.0];
    self.yLabelColor = [UIColor blackColor];
    self.xLabelFont = [UIFont fontWithName:@"Helvetica" size:11.0];
    self.xLabelColor = [UIColor greenColor];
    self.xLabelType = GraphViewXLabelTypeVerticle;
    //self.barTextFont = [UIFont fontWithName:@"Helvetica" size:9.0];
    //self.barTextColor = [UIColor whiteColor];
    //self.barTextType = GraphViewBarTextTypeTop;
    
    _barHeightRatio = (_gridLayer.bounds.size.height - 0) / (CGFloat)_topValue;
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.

- (void) drawCoordBkgd :(CGContextRef)ctx rt:(CGRect)rect iPad:(BOOL)bIpad
{
  //zone number font
  CGFloat fFonstSize = (bIpad?15.0:12.8);
  //CGFloat fWidCtrl = self.frame.size.height;
  if(_bHorBar) {
    int nRecvCount = [_dataSource totalRcvedCount];
    double dTimeInterval = [_dataSource HrateTimeInterval]; //2.0
    int nCount = _nXaxisCount;// + (_bViewDataRcd?1:0);
        
    //BOOL bIp4s = _bIp4s; //fWidCtrl < 134;
    CGFloat barWid = rect.size.width - leftMargin - rightMaring;
    CGFloat fVliHgt = (rect.size.height - _fBottomMargin) * (_yMaxLine - _yMinLine) / (_yMaxLine - _yMin);
    CGFloat fGrayHgt = rect.size.height - fVliHgt - _fBottomMargin * 1.1; 
    
    //CGFloat fGrayHgt = rect.size.height - fVliHgt - _fBottomMargin * 1.1;
    CGFloat barHgt =  fVliHgt / (_nBarCount + _nExtBarCount);
    CGFloat xPos = leftMargin / 2.0 + 13;
        
    CGContextSetLineWidth(ctx, 1.0);
    CGContextBeginPath(ctx);
    
    //zone number
    CGFloat xTxtPos = rect.size.width-(bIpad?25:15);
    //CGFloat fLastBmp = _yMin;
    for (int i=0; i<=_nBarCount; i++) {
      CGContextSetFillColorWithColor(ctx, _barColor[i].CGColor);
      //CGFloat y = rect.size.height - fVliHgt - _fBottomMargin - i * barHgt - kYScale * (bIpad?1:(bIp4s?-4.5:-3.6));
      CGFloat y = rect.size.height - _fBottomMargin - i * barHgt - fGrayHgt - 2;
      if(i == _nBarCount) {
        y -= barHgt * _nExtBarCount;
        barHgt += barHgt * _nExtBarCount;
      }
      CGRect barRect = CGRectMake(leftMargin, y, barWid,  (i==0)?fGrayHgt:barHgt);
        
      CGContextAddRect(ctx, barRect);
      CGContextFillPath(ctx);
      
      
      
      
      //draw coord text drawAtPoint
      float yCoordVal = (i==0)?_yMin: _yMinLine + (_yMaxLine - _yMinLine) * (i-1) / (_nBarCount+_nExtBarCount);
      NSString* sYcoordtxt = [NSString stringWithFormat:@"%.0f", yCoordVal];
      NSUInteger nLen = sYcoordtxt.length;
      //CGFloat yPos = (i==0)?(y+fGrayHgt-12): y + barHgt - 8;
      CGFloat yPos = (i==0)?(y+fGrayHgt-12): y + barHgt - 8;
      [self drawAtPoint:CGPointMake(leftMargin / 2.0 - ((nLen == 3)? 6: 0) - 7, yPos) withStr:sYcoordtxt color:[UIColor blackColor] font:bIpad?15:12.8 bold:NO];
           
      //draw coord line 0f y
      if(i == 0) {
        y = yPos + 12;
      }
      else {
        y += barHgt;
      }
      
      CGContextSetStrokeColorWithColor(ctx, [UIColor grayColor].CGColor);
      CGContextMoveToPoint(ctx, xPos, y);
      CGContextAddLineToPoint(ctx, xPos+12, y);
      
      CGContextStrokePath(ctx);
      
     //zone text
      CGFloat yZonePos = y - barHgt + barHgt/(bIpad?4.0:(_bIp6p?4.5:_bIp6?10.0:_bIp4s?-10.0:20.0));
      if(i > 0) {
        sYcoordtxt = [NSString stringWithFormat:@"%i", i];
        if(i == 1)
          yZonePos += barHgt / 1.5;
        else if(i == 5)
          yZonePos += barHgt / 4.5;
        [self drawAtPoint:CGPointMake(xTxtPos, yZonePos) withStr:sYcoordtxt
                    color:(_bViewDataRcd?[UIColor whiteColor]: [UIColor whiteColor]) font:fFonstSize bold:YES];
        
        //zone text
        //CGFloat txtPos = xTxtPos/2.0 - _asZoneTxt[i-1].length * 4.5;
        CGFloat txtPos = xTxtPos/4.0;
        [self drawAtPoint:CGPointMake(txtPos, yZonePos) withStr:_asZoneTxt[i-1]
                    color:[UIColor whiteColor] font:fFonstSize bold:NO];
      }
      
      //if(i > 0)
        //fLastBmp = fBmp;
    }
    //top one text and line with ycoord
    float yCoordVal = _fFitHRMax;//_yMaxLine;
    NSString* sYcoordtxt = [NSString stringWithFormat:@"%.0f", yCoordVal];
    NSUInteger nLen = sYcoordtxt.length;
    //CGFloat y = rect.size.height - _fBottomMargin -  _nBarCount * barHgt - fGrayHgt - 2;
    CGFloat ytPos = barHgt - _fBottomMargin - (_bIpad? 12:_bIp6p?14:_bIp6?10:3);//0;
    [self drawAtPoint:CGPointMake(leftMargin / 2.0 - ((nLen == 3)? 8: 0) - 5, ytPos) withStr:sYcoordtxt color:[UIColor blackColor] font:bIpad?15:12.8 bold:NO];
    //line pos
    ytPos += 9;
    CGContextSetStrokeColorWithColor(ctx, [UIColor grayColor].CGColor);
    CGContextMoveToPoint(ctx, xPos, ytPos);
    CGContextAddLineToPoint(ctx, xPos+12, ytPos);
    CGContextStrokePath(ctx);

      
    //draw bottom text
    xPos = leftMargin + (bIpad? 5: 3);
    NSDate* dtMeas = [[NSDate date] dateByAddingTimeInterval:-(nRecvCount * dTimeInterval)];
    if(_bMovrCurve) {
      if(_nMoveCurveTick == 0)
        _nMoveCurveTick = nRecvCount;
      dtMeas = [dtMeas dateByAddingTimeInterval:(nRecvCount - _nMoveCurveTick) * dTimeInterval];
      //_nMoveCurveTick++;
    }
        
    AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSDateFormatter* dtFmt = pApp.dtFmt;
    NSString* sDtFmt = dtFmt.dateFormat;
    //[dtFmt setTimeZone:NSLocal]
    [dtFmt setDateFormat:@"HH:mm"]; //for line only
      
    ////draw coord line of x
    CGContextBeginPath(ctx);
    //Pos -= bIpad? 20: 2;
    CGFloat dDelta = rect.size.width / (nCount) - (_bViewDataRcd?5:bIpad?2:5);
    CGFloat yPos = rect.size.height - _fBottomMargin - 2;// - (bIpad?5:_bIp6?-2:(bIp4s?2:2));
    for(int i=0; i<nCount; i++) {
      CGContextSetStrokeColorWithColor(ctx, [UIColor grayColor].CGColor);
      CGContextMoveToPoint(ctx, xPos, yPos);
      CGContextAddLineToPoint(ctx, xPos, yPos + (bIpad?12:8));
      CGContextStrokePath(ctx);
          
      if(_bViewDataRcd) {
        NSString* sTime = _sMeasTime[i];
        [self drawAtPoint:CGPointMake(xPos-(bIpad?27: 23), yPos + (bIpad?15:12)) withStr:sTime color:[UIColor blackColor] font:(bIpad?14.5:11.5) bold:NO];
      }
      else {
        NSString* sTime = [dtFmt stringFromDate: dtMeas];
        [self drawAtPoint:CGPointMake(xPos-(bIpad?19: 15), yPos + (bIpad?15:12)) withStr:sTime color:[UIColor blackColor] font:(bIpad?14.5:11.5) bold:NO];
      }
            
      xPos += dDelta;//rect.size.width / (nCount + 1);
      if(!_bViewDataRcd)
        dtMeas = [dtMeas dateByAddingTimeInterval:(bIpad?25:(_bIp6?12:11))*dTimeInterval];
    }
        
    //CGContextFillPath(ctx);
        
    [dtFmt setDateFormat:sDtFmt];
  }
  else {
    //return;
    CGFloat fCtrlWid = self.frame.size.width;
    BOOL bWider = fCtrlWid > 272;
    //CGFloat w = self.frame.size.width;
    //CGFloat xPos0 = leftMargin + self.frame.size.width / _nBarCount / 3.0;
    CGFloat xPos = leftMargin + self.frame.size.width / (_nBarCount) + (bIpad?14: (bWider?-15:-19)) - self.barWidth + 10;
    //if(!bWider)
      //xPos -= 2;
      
    CGContextSetStrokeColorWithColor(ctx, [UIColor grayColor].CGColor);
    CGContextBeginPath(ctx);
         
    NSString* sDurTime = NSLocalizedString(@"Time in", nil); //@"Intensity";
    CGFloat xTxtPos = leftMargin-self.barWidth / (bIpad?4.0: (bWider?1.12:(_bViewDataRcd?0.87:0.78)));
    if(xTxtPos < 0)
      xTxtPos = 0;
    if(!bIpad && fCtrlWid == 354)
      xTxtPos += 5;
    CGPoint ptTime = CGPointMake(xTxtPos + [UIScreen mainScreen].bounds.size.width / 25, rect.size.height - (bIpad?20:17) - (_bIp6p?10:12));
    [self drawAtPoint:ptTime withStr:sDurTime color:[UIColor colorWithRed:0.44 green:0.18 blue:0.53 alpha:1.00] font:bIpad?15.0:11.0 bold: NO];
    
    sDurTime = NSLocalizedString(@"Zone", nil);
    CGPoint ptZone = CGPointMake(xTxtPos + [UIScreen mainScreen].bounds.size.width / 25, rect.size.height - (bIpad?20:17) + 4);
    [self drawAtPoint:ptZone withStr:sDurTime color:[UIColor colorWithRed:0.44 green:0.18 blue:0.53 alpha:1.00] font:bIpad?15.0:11.0 bold: NO];
    
    for(int i=0; i<_nBarCount; i++) {
      CGContextMoveToPoint(ctx, xPos, rect.size.height - 20);
      CGContextAddLineToPoint(ctx, xPos, rect.size.height - 0); 
    
      
      sDurTime = _sTimeDur[i]; //@"5.05";
      NSDictionary *attrsDic = @{NSFontAttributeName: [UIFont systemFontOfSize:15.0]};
      CGSize txtLen = [sDurTime sizeWithAttributes:attrsDic];
      CGPoint pt = CGPointMake(xPos+(self.barWidth-txtLen.width)/2.0 + (_bBigScreen?3:0), rect.size.height - 18);
      //[self drawAtPoint:CGPointMake(xPos+self.barWidth/(bIpad?3.5:(bWider?5.0:8.0)), rect.size.height - 18) withStr:sDurTime color:[UIColor grayColor]];
      [self drawAtPoint:pt withStr:sDurTime color:[UIColor grayColor] font:bIpad?15.0:13.0 bold:NO];
      
      //draw zone number
      NSString* sNumTxt = [NSString stringWithFormat:@"%i", (short)(i+1)];
      pt.x += 9 + (_bBigScreen?2:0);
      if(i == 0 && _bBigScreen) {
        if(pt.x < 83)
           pt.x = 83;
      }
      
      pt.y -= rect.size.height / 3;
      //CGPoint pt = CGPointMake(xPos+10, rect.size.height - 0);
      [self drawAtPoint: pt withStr:sNumTxt color:[UIColor blackColor] font:fFonstSize bold:YES];
      
      xPos += self.barWidth;//(rect.size.width - leftMargin - rightMaring) / _nBarCount;
    }
        
    //CGContextMoveToPoint(ctx, xPos-3, rect.size.height - 20);
    //CGContextAddLineToPoint(ctx, xPos-3, rect.size.height - 0);
    CGContextMoveToPoint(ctx, xPos-1, rect.size.height - 20);
    CGContextAddLineToPoint(ctx, xPos-1, rect.size.height - 0);
    CGContextStrokePath(ctx);
        
    //[self reloadData];
    return;
        
    /*CGFloat fLeftMargin = leftMargin;
    if(bIpad)
      fLeftMargin *= 1.5;
        
    CGFloat barWid = (rect.size.width - fLeftMargin - rightMaring) / _nBarCount;
    CGFloat barHgt =  rect.size.height;
        
    for (int i=0; i<_nBarCount; i++) {
      CGContextSetFillColorWithColor(ctx, _barColor[i].CGColor);
      CGFloat x = i * barWid;
      CGRect barRect = CGRectMake(fLeftMargin+x, 0, barWid, barHgt);
      CGContextAddRect(ctx, barRect);
      CGContextFillPath(ctx);
            
      //draw text
      NSString* sYcoordtxt = [NSString stringWithFormat:@"%i", i + 1];
      [self drawAtPoint:CGPointMake(fLeftMargin+x+barWid/2 - 5, 5) withStr:sYcoordtxt];
    }
        
    //draw left text
    //CGFloat fWidth = self.frame.size.width ;
    //BOOL bWider = fWidth > 300; 
    CGFloat yPos = bIpad? 40: bWider?30:22;
    NSString* sLeftTxt = @"Time";
    if(bIpad)
      [self drawAtPoint:CGPointMake(14, yPos) withStr:sLeftTxt];
    else
      [self drawAtPoint:CGPointMake(6, yPos) withStr:sLeftTxt color:[UIColor grayColor] font:13.0 bold:NO];
      
    yPos += bIpad? 60: bWider?30:22;
    sLeftTxt = @"Points";
    [self drawAtPoint:CGPointMake(10, yPos) withStr:sLeftTxt];
        
    yPos += bIpad? 60: bWider?30:22;
    sLeftTxt = @"Percent";
    [self drawAtPoint:CGPointMake(0, yPos) withStr:sLeftTxt];
        
    //test data
    yPos = bIpad? 35: bWider?30:22;
    sLeftTxt = @"0.05";
    [self drawAtPoint:CGPointMake(leftMargin+(bIpad?barWid*3.0/5.0: barWid/5.0), yPos) withStr:sLeftTxt];*/
  }
}
//old version
/*- (void) drawCoordBkgd :(CGContextRef)ctx rt:(CGRect)rect iPad:(BOOL)bIpad
{
    CGFloat fHgtCtrl = self.frame.size.height;
    if(_bHorBar) {
        BOOL bWider = fHgtCtrl > 67;
        CGFloat barWid = rect.size.width - leftMargin - rightMaring;
        CGFloat barHgt =  (rect.size.height - _fBottomMargin)/ _nBarCount - 6;
        CGFloat xPos = leftMargin / 2.0 + 15;
        
        CGContextSetLineWidth(ctx, 1.0);
        CGContextBeginPath(ctx);
        
        for (int i=0; i<_nBarCount; i++) {
            CGContextSetFillColorWithColor(ctx, _barColor[i+1].CGColor);
            CGFloat y = rect.size.height - (i+1) * barHgt - _fBottomMargin - 29;
            
            CGRect barRect = CGRectMake(leftMargin, y, barWid,  barHgt);
            CGContextAddRect(ctx, barRect);
            CGContextFillPath(ctx);
            
            //draw coord textdrawAtPoint
            float yCoordVal = _yMin + (_yMaxLine - _yMin) * i / _nBarCount;
            NSString* sYcoordtxt = [NSString stringWithFormat:@"%.0f", yCoordVal];
            NSUInteger nLen = sYcoordtxt.length;
            [self drawAtPoint:CGPointMake(leftMargin / 2.0 - ((nLen == 3)? 8: 0) - 5, y + barHgt - 10) withStr:sYcoordtxt];
            
            //draw coord line
            CGContextSetStrokeColorWithColor(ctx, [UIColor grayColor].CGColor);
            CGContextMoveToPoint(ctx, xPos, y);
            CGContextAddLineToPoint(ctx, xPos+12, y);
            CGContextStrokePath(ctx);
            
            sYcoordtxt = [NSString stringWithFormat:@"ZONE %i", i+1];
            [self drawAtPoint:CGPointMake(rect.size.width-(bIpad?60:50), y + barHgt/(bIpad?3.0:5.0)) withStr:sYcoordtxt color:[UIColor blackColor] font:(bIpad?15.0:13.0)];
        }
        
        
        //draw bottom text
        xPos = leftMargin + barHgt - 10;
        NSDate* dtMeas = [NSDate date];
        if(_bMovrCurve)
            dtMeas = [dtMeas dateByAddingTimeInterval:-240];
        
        AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
        NSDateFormatter* dtFmt = [pApp dtFmt];
        NSString* sDtFmt = [dtFmt dateFormat];
        [dtFmt setDateFormat:@"H:mm"];
        
        CGContextBeginPath(ctx);
        int nCount = bIpad? 7: 6;
        for(int i=0; i<nCount; i++) {
            CGContextSetStrokeColorWithColor(ctx, [UIColor grayColor].CGColor);
            CGContextMoveToPoint(ctx, xPos, rect.size.height - 30);
            CGContextAddLineToPoint(ctx, xPos, rect.size.height -20);
            CGContextStrokePath(ctx);
            
            NSString* sTime = [dtFmt stringFromDate: dtMeas];
            [self drawAtPoint:CGPointMake(xPos-(bWider?20: 16), rect.size.height - 18) withStr:sTime color:[UIColor blackColor] font:bWider?15:12.0];
            
            xPos += rect.size.width / 8.0;
            dtMeas = [dtMeas dateByAddingTimeInterval:60];
        }
        
        //CGContextFillPath(ctx);
        
        [dtFmt setDateFormat:sDtFmt];
    }
    else {
        BOOL bWider = self.frame.size.height > 250;
        //CGFloat w = self.frame.size.width;
        //CGFloat xPos0 = leftMargin + self.frame.size.width / _nBarCount / 3.0;
        CGFloat xPos = leftMargin + self.frame.size.width / (_nBarCount) + (bIpad?14: (bWider?-15:-19)) - self.barWidth;
        
        CGContextSetStrokeColorWithColor(ctx, [UIColor grayColor].CGColor);
        CGContextBeginPath(ctx);
        
        NSString* sDurTime = @"Time";
        CGPoint pt = CGPointMake(leftMargin-self.barWidth / (bIpad?10.0: (bWider?1.2:(_bViewDataRcd?0.90:0.85))), rect.size.height - (bIpad?18:19));
        [self drawAtPoint:pt withStr:sDurTime color:[UIColor grayColor] font:bIpad?15.0:13.0];
        for(int i=0; i<_nBarCount; i++) {
            CGContextMoveToPoint(ctx, xPos, rect.size.height - 20);
            CGContextAddLineToPoint(ctx, xPos, rect.size.height - 0);
            
            sDurTime = _sTimeDur[i]; //@"5.05";
            NSDictionary *attrsDic = @{NSFontAttributeName: [UIFont systemFontOfSize:15.0]};
            CGSize txtLen = [sDurTime sizeWithAttributes:attrsDic];
            //[self drawAtPoint:CGPointMake(xPos+self.barWidth/(bIpad?3.5:(bWider?5.0:8.0)), rect.size.height - 18) withStr:sDurTime color:[UIColor grayColor]];
            [self drawAtPoint:CGPointMake(xPos+(self.barWidth-txtLen.width)/2.0, rect.size.height - 18) withStr:sDurTime color:[UIColor grayColor] font:bIpad?15.0:13.0];
            xPos += self.barWidth;//(rect.size.width - leftMargin - rightMaring) / _nBarCount;
        }
        CGContextMoveToPoint(ctx, xPos, rect.size.height - 20);
        CGContextAddLineToPoint(ctx, xPos, rect.size.height - 0);
        CGContextStrokePath(ctx);
        
        [self reloadData];
        return;
        CGFloat fLeftMargin = leftMargin;
        if(bIpad)
            fLeftMargin *= 1.5;
        
        
        CGFloat barWid = (rect.size.width - fLeftMargin - rightMaring) / _nBarCount;
        CGFloat barHgt =  rect.size.height;
        
        for (int i=0; i<_nBarCount; i++) {
            CGContextSetFillColorWithColor(ctx, _barColor[i].CGColor);
            CGFloat x = i * barWid;
            CGRect barRect = CGRectMake(fLeftMargin+x, 0, barWid, barHgt);
            CGContextAddRect(ctx, barRect);
            CGContextFillPath(ctx);
            
            //draw text
            NSString* sYcoordtxt = [NSString stringWithFormat:@"%i", i + 1];
            [self drawAtPoint:CGPointMake(fLeftMargin+x+barWid/2 - 5, 5) withStr:sYcoordtxt];
        }
        
        //draw left text
        //CGFloat fWidth = self.frame.size.width ;
        //BOOL bWider = fWidth > 300; 
        CGFloat yPos = bIpad? 40: bWider?30:22;
        NSString* sLeftTxt = @"Time";
        [self drawAtPoint:CGPointMake(18, yPos) withStr:sLeftTxt];
        
        yPos += bIpad? 60: bWider?30:22;
        sLeftTxt = @"Points";
        [self drawAtPoint:CGPointMake(10, yPos) withStr:sLeftTxt];
        
        yPos += bIpad? 60: bWider?30:22;
        sLeftTxt = @"Percent";
        [self drawAtPoint:CGPointMake(0, yPos) withStr:sLeftTxt];
        
        //test data
        yPos = bIpad? 35: bWider?30:22;
        sLeftTxt = @"0.05";
        [self drawAtPoint:CGPointMake(leftMargin+(bIpad?barWid*3.0/5.0: barWid/5.0), yPos) withStr:sLeftTxt];
        
    }
    
    //_bRedraw = YES;
}*/

- (void)drawRect:(CGRect)rect
{
  BOOL bIpad = _bIpad;//self.frame.size.width > 500;
        
  CGContextRef ctx = UIGraphicsGetCurrentContext();
  //CGContextClearRect(ctx, rect);
  [self drawCoordBkgd:ctx rt:rect iPad:bIpad];
    
  if(!_bHorBar)
    return;
    
    
  CGContextSetLineJoin(ctx, kCGLineJoinRound);
  CGContextSetStrokeColorWithColor(ctx, [GraphColor CGColor]);
  CGContextSetLineWidth(ctx, 1.5);
    
  CGFloat H = self.bounds.size.height - _fBottomMargin;
  //CGFloat W = self.bounds.size.width - leftMargin - rightMaring;
  CGFloat yOffset = H / kYScale;//_yMin;
    
  //CGAffineTransform transform = CGAffineTransformMakeScaleTranslate(kXScale, kYScale, 0, yOffset);;
  CGAffineTransform transform = CGAffineTransformMakeScaleTranslate(kXScale, kYScale, 0, yOffset);
    
  CGFloat xOff = leftMargin / kXScale + (_bViewDataRcd?kXSpan*1.2:kXSpan*1.2);
    
  if ([self.values count] == 0) {
    return;
  }
    
  CGMutablePathRef curvePath = CGPathCreateMutable();
  CGMutablePathRef elliPath = CGPathCreateMutable();
    
  //CGContextSetLineDash(ctx, 0, NULL, 0);
  CGContextSetStrokeColorWithColor(ctx, [UIColor blackColor].CGColor);
  CGContextSetLineWidth(ctx, 2.0);
    
  CGFloat fxyRate = kYScale / kXScale;
  CGFloat y = -[[self.values objectAtIndex:0] floatValue] / kYScale;// * H / _yMaxLine;
    
  NSUInteger nUpIdx = [self.values count];
  CGFloat xSpan = 1;
  
  if(_bViewDataRcd) {
    xSpan = (rect.size.width - (_bIpad?25:(_bIp6?50:20))) / nUpIdx / 4.2;
    if(nUpIdx < 5) {
      xSpan *= 1.23;
      xOff += 5;
    }
    if(nUpIdx < 8) {
      xSpan *= 1.15;
      xOff += 5;
    }
    else if(nUpIdx < 12) {
      xSpan *= 1.05;
      xOff += 5;
    }
    else {
      //if(_bIp4s)
        //®xOff *= 1.75;
      xSpan *= 0.95;
      xOff += 0;
    }
    xSpan *= (1.0 + 1.0 / (_nXaxisCount-1));
  }
  CGPathAddEllipseInRect(elliPath, &transform, CGRectMake((xOff-1.0*fxyRate), (y-1.0), 2*fxyRate, 2));
  CGPathMoveToPoint(curvePath, &transform, (xOff+1.0*fxyRate), (y+0.0));
  
  CGFloat fRate = _bIp4s?1.25:_bIp6p?0.95:1.0;
  for (NSUInteger x = 1; x < nUpIdx; x++) {
    y = -[[self.values objectAtIndex:x] floatValue] / kYScale;// + _yMaxLine;// * H / _yMaxLine;
        
    CGFloat xx = (xOff + x * kXSpan * xSpan) * fRate;
    CGPathAddLineToPoint(curvePath, &transform, xx-1.0*fxyRate, (y-0.0));
    if((_bViewDataRcd && (nUpIdx < 20)) || (x == nUpIdx - 1))
      CGPathAddEllipseInRect(elliPath, &transform, CGRectMake((xx-1.0*fxyRate), (y-1.0), 2*fxyRate, 2));
  }
    
  CGContextAddPath(ctx, curvePath);
  CGContextAddPath(ctx, elliPath);
  CGContextStrokePath(ctx);
  
  CGPathRelease(curvePath);
  CGPathRelease(elliPath);
}

- (void) setFitnessHrates:(float)fMaxVal
{
  _fFitHRMax = fMaxVal;
  _fMinHRVal = fMaxVal * 0.5;
  _fMaxHRVal = fMaxVal * 0.7;
  //float fDelta = fMaxVal * 0.5 / _nDurtBarNumber;
  
  _yMinLine =_fMinHRVal;
  if(_nExtBarCount == 2)
    _yMaxLine = fMaxVal * 1.2;
  else if(_nExtBarCount == 1)
    _yMaxLine = fMaxVal * 1.1;
  else
    _yMaxLine = fMaxVal;
 
  _yMin = 55; //_fMinHRVal - fDelta * 1; //55;
  _yAvgVal = (_yMaxLine + _yMin) / 2.0;
 
  /*if(_bIpad)
    _yAvgVal -= _fBottomMargin / kYScale / 5.0;
  else if(_bIp6)
    _yAvgVal += _fBottomMargin / kYScale / 2.0;*/
}

- (void) setFitnessRngBpm:(float) fMinVal maxHrt:(float)fMaxVal
{
    _fMinHRVal = fMinVal;
    _fMaxHRVal = fMaxVal;
    float fDelta = (fMaxVal - fMinVal) / 2;
    _yMinLine = fMinVal - fDelta;
    _yMin = _yMinLine / 2;
    _yMaxLine = fMinVal + fDelta * 4;
    
    _yAvgVal = (_yMaxLine + _yMin) / 2.0 - _yMaxLine / (_bIpad? 700:(_bIp6?600:(_bIp4s?480: 500.0)));
    _yAvgVal -= _yMin / (_bIpad? 700:(_bIp6?600:(_bIp4s?480.0:500.0)));
    if(_bIpad)
        _yAvgVal -= _fBottomMargin / kYScale / 5.0;
    else if(_bIp6)
        _yAvgVal += _fBottomMargin / kYScale / 2.0;
    
    /*_yAvgVal = (_yMaxLine + _yMin) / 2;
    _yAvgVal -= _yMin / (_bIpad?2.0:(_bIp6?0.5: (_bIp4s?1.5:1.0)));
    if(_bIpad)
        _yAvgVal += _fBottomMargin * kYScale * 20.0;
    else if(_bIp6)
        _yAvgVal -= _fBottomMargin * kYScale * 10.0;*/
}
/*- (void) setFitnessHrates:(float) fMinVal maxHrt:(float)fMaxVal
{
    _fMinHRVal = fMinVal;
    _fMaxHRVal = fMaxVal;
    float fDelta = (fMaxVal - fMinVal) / 2;
    _yMinLine = fMinVal - fDelta;
    _yMin = _yMinLine;
    _yMaxLine = fMinVal + fDelta * 4;
    
    _yAvgVal = (_yMaxLine + _yMin) / 2.0 - _yMaxLine / (_bIpad? 700:(_bIp6?600:(_bIp4s?480: 500.0)));
    _yAvgVal -= _yMin / (_bIpad? 700:(_bIp6?600:(_bIp4s?480.0:500.0)));
    if(_bIpad)
        _yAvgVal -= _fBottomMargin / kYScale / 5.0;
    else if(_bIp6)
        _yAvgVal += _fBottomMargin / kYScale / 2.0;
}*/
- (void) addHrmMeasVal:(short)hHrate;
{
  if(hHrate < _yMin) //low val not display
    return;
  double nextValue = 0;
  
  //CGFloat yPos = self.bounds.size.height / 2.0;
  CGFloat H = self.bounds.size.height - _fBottomMargin;
  BOOL bIpad = H > 331;
  if(hHrate < _yMinLine - 1) {
    H *=  _bIpad?0.9:0.8;
    nextValue = (hHrate - _yAvgVal) * H / (_yMaxLine - _yMin);
  }
  else {
    H *=  _bIpad?0.95: (_bIp6?1.15:1.10);
    nextValue = (hHrate - _yAvgVal) * H / (_yMaxLine - _yMin);
  }
  
  [self.values addObject:[NSNumber numberWithDouble:nextValue]];
  CGSize size = self.bounds.size;
  
  CGFloat     maxDimension = (size.width - leftMargin - rightMaring) / (kXSpan + 1.36); // MAX(size.height, size.width);
  NSUInteger  maxValues = (NSUInteger)floorl(maxDimension / kXScale);
  if(bIpad) //iPad
    maxValues += 20;
  
  if ([self.values count] > maxValues && !_bViewDataRcd) {
    [self.values removeObjectsInRange: NSMakeRange(0, [self.values count] - maxValues)];
    _bMovrCurve = YES;
  }

}

- (void) updateValues:(short)hHrate
{
  //if(hHrate < _yMin) //low val not display
    //return;
  double nextValue = 0;
    
  //CGFloat yPos = self.bounds.size.height / 2.0;
  CGFloat H = self.bounds.size.height - _fBottomMargin;
  BOOL bIpad = H > 331;
  BOOL bIp6 = NO;
  if(!bIpad)
    bIp6 = H >187;
  /*short nDelta = _yMinLine - _yMin;
  short nStep1 = _yMin + nDelta / 4;
  short nStep2 = _yMin + nDelta * 3 / 4;
  short nStep3 = _yMinLine;
  short nStep4 = _yMinLine + nDelta / 2;
  short nStep5 = _yAvgVal;
  short nStep6 = _yAvgVal + nDelta / 2;
  
  if(hHrate >= _yMin && hHrate < nStep1)
    H *= (_bIpad? 0.905:0.90);
  else if(hHrate < nStep1)
    H *= (_bIpad?0.925:0.92);
  else if(hHrate < nStep2)
    H *= (_bIpad?0.940:0.92);
  else if(hHrate < nStep3)
    H *= (_bIpad?0.950:0.92);
  else if(hHrate < nStep4)
    H *= (_bIpad?0.955:0.92);
  else if(hHrate < nStep5)
    H *= (_bIpad?0.940:0.93);
  else if(hHrate < nStep6)
    H *= (_bIpad?0.935:0.93);
  else
    H *= (_bIpad?0.93:1.00);*/
  nextValue = (hHrate - _yAvgVal) * H / (_yMaxLine - _yMin);
    
  [self.values addObject:[NSNumber numberWithDouble:nextValue]];
  CGSize size = self.bounds.size;

  CGFloat     maxDimension = (size.width - leftMargin - rightMaring) / (kXSpan + 1.36); // MAX(size.height, size.width);
  NSUInteger  maxValues = (NSUInteger)floorl(maxDimension / kXScale) + (bIp6?13:11);
  if(bIpad) //iPad
    maxValues += 21;
    
  if ([self.values count] > maxValues && !_bViewDataRcd) {
    [self.values removeObjectsInRange: NSMakeRange(0, [self.values count] - maxValues)];
    _bMovrCurve = YES;
  }
  
  if(!_bViewDataRcd)
    [self setNeedsDisplay];
}

/*- (void) updateValues:(short)hHrate
{
    CGFloat fDelta = (_fMaxHRVal - _fMinHRVal) / 2;
    if(hHrate < _yMinLine - fDelta) //low val not display
        return;
    
    double nextValue = 0;
    
    //CGFloat yPos = self.bounds.size.height / 2.0;
    CGFloat H = self.bounds.size.height - _fBottomMargin;
    H *=  _bIpad?0.95: (_bIp6?1.00:1.05);
    nextValue = (hHrate - _yAvgVal) * H / (_yMaxLine - _yMin);
    //just now low bar
    nextValue = nextValue * (_bIpad?0.905: (_bIp6?0.810:0.750)) + _yMin * (_bIpad?0.045: (_bIp6?0.355:0.215)); //the line only for no low bat to show data
    
    [self.values addObject:[NSNumber numberWithDouble:nextValue]];
    CGSize size = self.bounds.size;
    
    CGFloat     maxDimension = (size.width - leftMargin - rightMaring) / (kXSpan + 1.36); // MAX(size.height, size.width);
    NSUInteger  maxValues = (NSUInteger)floorl(maxDimension / kXScale);
    if(H > 365) //iPad
        maxValues += 20;
    
    if ([self.values count] > maxValues) {
        [self.values removeObjectsInRange: NSMakeRange(0, [self.values count] - maxValues)];
        _bMovrCurve = YES;
    }
    
    [self setNeedsDisplay];
}*/

-(double) showHrateItem:(NSMutableArray*)pHrateItem
{
  double dDurSecs = 0;
  [self.values removeAllObjects];
  if(pHrateItem == nil) {
    for(int i=0; i<=_nBarCount; i++) {
      _sTimeDur[i] = @"0.00";
    }
    [self setNeedsDisplay];
    if(!_bHorBar)
      [self reloadData];
    return 0.0;
  }
  
    
  AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  NSDateFormatter* dtFmt = [pApp dtFmt];
  NSString* sDtFmt = [dtFmt dateFormat];
  if(_bViewDataRcd)
    [dtFmt setDateFormat:@"HH:mm:ss"];
  else
    [dtFmt setDateFormat:@"HH:mm:ss"];
    
  int nMaxIdx =_nXaxisCount - 1;
  NSDate* dtFirst = nil;
  NSDate* dtLast = nil;
    
  NSUInteger nCount = pHrateItem.count;
  for(NSUInteger i = 0; i<nCount; i++) {
    H_RateItem* pItem = (H_RateItem*)[pHrateItem objectAtIndex:i];
    if(i == 0) {
      dtFirst = pItem.hRateTime;
      _sMeasTime[0] = [dtFmt stringFromDate:pItem.hRateTime];
    }
    else if(i == nCount-1) {
      dtLast = pItem.hRateTime;
      _sMeasTime[nMaxIdx] = [dtFmt stringFromDate:pItem.hRateTime];
    }
        //_sMeasTime[i] = [dtFmt stringFromDate:pItem.hRateTime];
        
    short nHrate = [pItem.hRateValue shortValue];
    [self updateValues:nHrate];
  }
    
  //other meas time;
  if(dtFirst != nil && dtLast != nil) {
    double dDelta = [dtLast timeIntervalSinceDate:dtFirst] / nMaxIdx + 0.1;
    for(int i=1; i < nMaxIdx; i++) {
      _sMeasTime[i] = [dtFmt stringFromDate:[dtFirst dateByAddingTimeInterval:dDelta * i]];
    }
    dDurSecs = [dtLast timeIntervalSinceDate:dtFirst];//dDelta * nMaxIdx;
  }
    
  [pApp.dtFmt setDateFormat:sDtFmt];
  [self setNeedsDisplay];
    
  return dDurSecs;
}

- (CGFloat) showHrateDurTime:(NSMutableArray*)pHrateItem start:(NSDate*)dtStart
{
  CGFloat pHrate[_nDurtBarNumber];
  
  CGFloat fMax = 0;
  for(int i = 0; i<_nBarCount; i++) {
    pHrate[i] = 0.0;
  }
  if(pHrateItem == nil) {
    for(int i=0; i<_nDurtBarNumber; i++) {
      [self setTimeRngDur:i dur:0.0];
    }
    [self reloadData];
    return 35.0;
  }
    
  NSDate* dtLast = dtStart;
  NSUInteger nCount = pHrateItem.count;
  for(NSUInteger i = 0; i<nCount; i++) {
    H_RateItem* pItem = (H_RateItem*)[pHrateItem objectAtIndex:i];
    short nHrate = [pItem.hRateValue shortValue];
    int nIdx = [self getHrateRngIdx:nHrate];
    if((dtLast != nil) && (nIdx > 0 && nIdx <= _nDurtBarNumber)) {
      NSDate* dtMeas = pItem.hRateTime;
      double dDecDur = [dtMeas timeIntervalSinceDate:dtLast];
       //pHrate[i] += dDecDur;
      pHrate[nIdx-1] += dDecDur;
    }
    dtLast = pItem.hRateTime;
  }
  
  //H_RateItem* pItemLast = (H_RateItem*)[pHrateItem objectAtIndex:nCount-1];
  //dtLast = pItemLast.hRateTime;
    
  for(int i=0; i<_nDurtBarNumber; i++) {
    _afDurTime[i] = pHrate[i];
    [self setTimeRngDur:i dur:pHrate[i]];
    if(pHrate[i] > fMax)
      fMax = pHrate[i];
  }
  
  if(fMax == 0)
    fMax = 35.0;

  _fMaxDurVal = fMax;
  //[self reloadData];
  
  return fMax;
}

- (CGFloat*) getBandDurTime
{
  return _afDurTime;
}

- (void)dealloc
{
    //dispatch_source_cancel(_timer);
}

- (void) drawAtPoint:(CGPoint)point withStr:(NSString *)str color:(UIColor*)col font:(CGFloat)fSize bold:(BOOL)bBold
{
  NSDictionary *attrsDic = @{NSFontAttributeName: bBold?[UIFont boldSystemFontOfSize:fSize]:[UIFont systemFontOfSize:fSize], NSForegroundColorAttributeName:col};
   [str drawAtPoint:point withAttributes:attrsDic];
}


- (void) drawAtPoint:(CGPoint)point withStr:(NSString *)str
{
    NSDictionary *attrsDic = @{NSFontAttributeName: [UIFont systemFontOfSize:15.0], NSForegroundColorAttributeName:[UIColor grayColor]};
    if (IOS7_OR_LATER) {
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1
        //[str drawAtPoint:point withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:8], NSStrokeColorAttributeName:GraphColor}];
        [str drawAtPoint:point withAttributes:attrsDic];
#endif
    } else {
        //[str drawAtPoint:point withFont:[UIFont systemFontOfSize:8]];
        [str drawAtPoint:point withAttributes:attrsDic];
    }
    
}

#pragma mark Bars
- (void) reloadData
{
    if (!_dataSource || _bHorBar)
        return;
    //_bDrawCurve = _numberOfBars > _nSwitchCount;
    
    [_barHeights removeAllObjects];
    [_barLabels removeAllObjects];
    [_barTexts removeAllObjects];
    [_barHoriPos removeAllObjects];
    
    // Collect some data
    for (NSInteger i = 0; i < _numberOfBars; i++) {
        [_barHeights addObject:[NSNumber numberWithFloat:[_dataSource barChart:self valueForBarAtIndex:i]]];
        
        //float fHrate = [_dataSource barChart: self lTimeForBarAtIndex:i];
        //if([_dataSource barChart: self hTimeForBarAtIndex:i] >fHrate)
            //fHrate = [_dataSource barChart: self hTimeForBarAtIndex:i];
        //[_hrtHeights addObject:[NSNumber numberWithFloat:fHrate]];

        if (_dataSource && [_dataSource respondsToSelector:@selector(barChart:xLabelForBarAtIndex:)])
            [_barLabels addObject:[_dataSource barChart:self xLabelForBarAtIndex:i]];
        if (_dataSource && [_dataSource respondsToSelector:@selector(barChart:textForBarAtIndex:)])
            [_barTexts addObject:[_dataSource barChart:self textForBarAtIndex:i]];
    }
    if(_numberOfBars > 0) {
      _maxHeight		= [_barHeights valueForKeyPath:@"@max.self"];
      _minHeight		= [_barHeights valueForKeyPath:@"@min.self"];
      
      if(_barHoriPos.count > 0) {
        _maxWidth		= [_barHoriPos valueForKeyPath:@"@max.self"];
        _minWidth		= [_barHoriPos valueForKeyPath:@"@min.self"];
      }
      
      if(_hrtHeights != nil) {
        NSNumber* fMaxHrate = [_hrtHeights valueForKeyPath:@"@max.self"];
        if(fMaxHrate.floatValue > _maxHeight.floatValue)
          _maxHeight = fMaxHrate;
      }
      
    }
    else {
        _maxHeight = [NSNumber numberWithInteger:200];
        _minWidth = [NSNumber numberWithInteger:0];
        _maxWidth = [NSNumber numberWithInteger:1];
        _minWidth = [NSNumber numberWithInteger:0];
    }
    
    //self.incrementValue = (_nSetUnit == 2)? 50 : 100;
    
    
    self.incrementValue = 100;
    
   
    if(_maxHeight.floatValue < 1) {
        _topValue = 1;
        self.incrementValue = 1;
    }
    else {
        _topValue = (_maxHeight.floatValue * 1.25 + 1.0);
        if(_topValue >= 4)
            self.incrementValue = _topValue / 4;
        else
            self.incrementValue = 1;
    }
        //_rightValue     = _maxWidth.integerValue - _minWidth.integerValue + 1.0;
   
    _rightValue = _maxWidth.integerValue - _minWidth.integerValue + 1.0;
    
   
    self.incrementValue = 10;
    _topValue = 40;
   
    
    // Round up to the next increment value
    if (_dataSource) 	{
        // Find max height of the x Labels based on the angle of rotation of the text
        switch (self.xLabelType) {
            case GraphViewXLabelTypeVerticle:
            default:
                _xLabelRotation = 90.0;
                break;
                
            case GraphViewXLabelTypeHorizontal:
                _xLabelRotation = 0.0;
                break;
                
            case GraphViewXLabelTypeAngled:
                _xLabelRotation = 45.0;
                break;
        }
        
        for (NSString *label in _barLabels) {
            //CGSize labelSize = [label sizeWithFont:self.xLabelFont];
            CGSize labelSize = [label sizeWithAttributes:@{NSFontAttributeName: self.xLabelFont}];
            CGFloat labelHeightWithAngle = sin(DEGREES_TO_RADIANS(_xLabelRotation)) * labelSize.width;
            
            if (labelSize.height > labelHeightWithAngle)	{
                _xLabelMaxHeight = (_xLabelMaxHeight > labelSize.height) ? _xLabelMaxHeight : labelSize.height;
            }
            else {
                _xLabelMaxHeight = (_xLabelMaxHeight > labelHeightWithAngle) ? _xLabelMaxHeight : labelHeightWithAngle;
            }
        }
        
        /*     Begin Drawing     */
        // Set Frames
        //CGSize yLabelSize		= self.hasYLabels ? [[NSString stringWithFormat:@"%i", (int)_topValue] sizeWithFont:self.yLabelFont] : CGSizeZero;
        CGSize yLabelSize		= self.hasYLabels ? [[NSString stringWithFormat:@"%i", (int)_topValue] sizeWithAttributes:@{NSFontAttributeName:self.yLabelFont}] : CGSizeZero;
        _yLabelView.frame		= CGRectMake(0.0, 0.0,
                                             self.hasYLabels ? yLabelSize.width + 5.0 : 0.0,
                                             self.bounds.size.height);
        
        _xLabelView.frame		= CGRectMake(_yLabelView.frame.origin.x + _yLabelView.frame.size.width,
                                             self.bounds.size.height - _xLabelMaxHeight,
                                             self.bounds.size.width - (_yLabelView.frame.origin.x + _yLabelView.frame.size.width),
                                             _xLabelMaxHeight);
        
        _gridLayer.frame		= CGRectMake(_yLabelView.frame.origin.x + _yLabelView.frame.size.width, 0.0,
                                             self.bounds.size.width - (_yLabelView.frame.origin.x + _yLabelView.frame.size.width),
                                             self.bounds.size.height - (_xLabelMaxHeight > 0.0 ? (_xLabelMaxHeight + 5.0) : 0.0));
        _barLayer.frame			= _gridLayer.frame;
        _borderLayer.frame		= _gridLayer.frame;
        _barTextView.frame		= _gridLayer.frame;
        
        //_barHeightRatio  = _barLayer.bounds.size.height / (CGFloat)_topValue;
        //_barWidthRatio   = (_barLayer.bounds.size.width - self.incrmtxposValue * 2) / (CGFloat)_rightValue;
        _barHeightRatio  = (_gridLayer.bounds.size.height - 0)  / (CGFloat)_topValue;
        _barWidthRatio   = (_gridLayer.bounds.size.width - self.incrmtxposValue * 2) / (CGFloat)_rightValue;
        
        if (_barHeightRatio < 1) {
            _barHeightRatio = _gridLayer.bounds.size.height / (CGFloat)_topValue;
        }
        if (_barWidthRatio < 1) {
            _barWidthRatio = (_gridLayer.bounds.size.width - self.incrmtxposValue * 2) / (CGFloat)_rightValue;
        }
        
        
        // Draw dem stuff
        //[self setupBorders];
        //[self drawBorders];
        
      if(!_bHorBar) {
        @autoreleasepool {
          [self setupBars];
          [self animateBarAtIndex:0];
        }
      }
      else {
        [self.layer setNeedsDisplay];
      }
      
        
        /*if (self.hasGrids)
        {
            [self setupGrid];
            [self drawGrid];
        }*/
        
        //[self setupYAxisLabels];
        //[self setupXAxisLabels];
        
        //if(!_bDrawCurve)
            //[self setupBarTexts];
        
        //if(_nSetUnit < 200) {
        //draw goals mark
        //[self.layer setNeedsDisplay];
        //[self drawGoalsStarMark];
        //}
    }
}

- (void)setupBars
{
  if(_bHorBar)
    return;
  // Clear all bars for each drawing
  for (CAShapeLayer *layer in _barPathLayers) {
    if (layer != nil) {
      [layer removeFromSuperlayer];
    }
  }
  [_barPathLayers removeAllObjects];
  
  BOOL bWider = self.frame.size.width > 272;
  CGFloat barHeightRatio	= _barHeightRatio;
  CGFloat	xPos			= self.frame.size.width / (_nBarCount + 1) + 10;
  //if(self.frame.size.width < 272)
    //xPos -= 2;
  xPos += _bIpad?31:(_bIp6p?16.5:(_bIp6?19:(_bIp4s?19:18)));
    //CGFloat	xPos = leftMargin + self.frame.size.width / (_nBarCount) + (_bIpad?14: (_bIp6?-15:-19)) - self.barWidth;
    
  if(_bViewDataRcd)
    xPos -= _bIpad?1:(_bIp6p?0:(_bIp6?0:(_bIp4s?1:1)));
  
  CGFloat fBarWid = self.barWidth;
  for (NSInteger i = 0; i < _nBarCount; i++)	{
    if(_barHeights.count == 0) {
      return;
    }
    else if(i==_nBarCount-1) {
      xPos -= 0.55;
      fBarWid -= 1;
    }
    
    //draw zone number
    /*if(!_bHorBar) {
      NSString* sNumTxt = [NSString stringWithFormat:@"%i", (short)(i+1)];
      CGPoint pt = CGPointMake(xPos+10, 80);
      [self drawAtPoint: pt withStr:sNumTxt color:[UIColor redColor] font:30.0 bold:YES];
    }*/
    
    //xPos += self.barWidth * i;
    CGPoint bottom = CGPointMake(xPos, _barLayer.bounds.origin.y);
    if(([_barHeights objectAtIndex:i]) == nil)
      break;
    
    //CGFloat yPos = ((NSNumber *)[_barHeights objectAtIndex:i]).floatValue;
    CGPoint top	= CGPointMake(xPos, ((NSNumber *)[_barHeights objectAtIndex:i]).floatValue * barHeightRatio);
        
    //bottom.y = [_dataSource barChart:self lPresForBarAtIndex:i] * barHeightRatio;
        
    UIBezierPath *path				= [UIBezierPath bezierPath];
    [path moveToPoint:bottom];
      
    if(_bResetData)
      [path addLineToPoint:bottom];
    else
      [path addLineToPoint:top];
        
        //float fWgtVal = ((NSNumber *)[_barHeights objectAtIndex:i]).floatValue;
        //BOOL bLessGoal = fWgtGoal == 0 || fWgtVal <= fWgtGoal;
        
        UIColor *barColor = [UIColor colorWithRed:0.75 green:0.75 blue:0.75 alpha:1.0];
        if (_dataSource && [_dataSource respondsToSelector:@selector(barChartColor:)])
            barColor = [_dataSource barChartColor:i+1];
        else
            barColor = _barColor[i+1];
        
        
        CAShapeLayer *barPathLayer		= [CAShapeLayer layer];
        barPathLayer.frame            = _barLayer.bounds;
        barPathLayer.bounds           = _barLayer.bounds;
        barPathLayer.geometryFlipped  = YES;
        barPathLayer.path             = path.CGPath;
        barPathLayer.strokeColor      = barColor.CGColor;//[barColor colorWithAlphaComponent:self.barAlpha].CGColor;
        barPathLayer.fillColor        = nil;
        barPathLayer.lineWidth        = fBarWid;
        barPathLayer.lineJoin         = kCALineJoinBevel;
        barPathLayer.hidden           = YES;
        //barPathLayer.shadowOffset		= self.barShadowOffset;
        //barPathLayer.shadowColor    = self.barShadowColor.CGColor;
        //barPathLayer.shadowOpacity	= self.barShadowAlpha;
        //barPathLayer.shadowRadius		= self.barShadowRadius;
        
        [_barLayer addSublayer:barPathLayer];
        [_barPathLayers addObject:barPathLayer];
        
        //heart rate
       
        /*UIBezierPath *hPath			= [UIBezierPath bezierPath];
        CGFloat hRate = [_dataSource barChart:self hRateForBarAtIndex:i] * barHeightRatio;
        //hPath.lineWidth = 2;
        [hPath moveToPoint:CGPointMake(bottom.x+5, hRate)];
        [hPath addArcWithCenter:CGPointMake(bottom.x, hRate) radius:5 startAngle:0 endAngle:M_PI*2 clockwise:YES];
        //[hPath stroke];
            
        CAShapeLayer *hrateLayer		= [CAShapeLayer layer];
        hrateLayer.frame				= _barLayer.bounds;
        hrateLayer.bounds			= _barLayer.bounds;
        hrateLayer.geometryFlipped   = YES;
        hrateLayer.path				= hPath.CGPath;
        hrateLayer.strokeColor       = [_dataSource barChart:self colorForBarAtIndex:4].CGColor;//[UIColor greenColor].CGColor;
        //hrateLayer.strokeColor       = [UIColor colorWithRed:0.0 green: 0.45 blue: 0.01 alpha:0.75].CGColor;
        hrateLayer.fillColor         = nil;
        hrateLayer.lineWidth         = 2;
        hrateLayer.lineJoin			= kCALineJoinBevel;
        hrateLayer.hidden			= YES;
        //hrateLayer.shadowOffset		= self.barShadowOffset;
        //hrateLayer.shadowColor       = self.barShadowColor.CGColor;
        // hrateLayer.shadowOpacity     = self.barShadowAlpha;
        //hrateLayer.shadowRadius		= self.barShadowRadius;
            
        [_barLayer addSublayer:hrateLayer];
        [_barPathLayers addObject:hrateLayer];*/
                
        
        /*CIColor* color = barColor.CIColorƒ;
         color.red = 0.75;
         color.green = 0.75;
         color.blue = 0.75;*/
        
      xPos +=  self.barWidth + (bWider?0.4:0.2);
    }
}

- (void)animateBarAtIndex:(NSInteger)index
{
    if (index >= _barPathLayers.count) {
        // Last bar, begin drawing grids
        [self displayAxisLabels];
        return;
    }
    
    if(self.hasYLabels) {
        __block NSInteger i = index + 1;
        __weak UICurveView *weakSelf = self;
        [CATransaction begin];
        [CATransaction setAnimationDuration:(self.animationDuration / (CGFloat)_barPathLayers.count)];
        [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
        [CATransaction setCompletionBlock:^{
            [weakSelf animateBarAtIndex:i];
        }];
        
        CAShapeLayer *barPathLayer		= [_barPathLayers objectAtIndex:index];
        barPathLayer.hidden				= NO;
        [self drawBar:barPathLayer];
        
        [CATransaction commit];
    }
}

- (void)drawBar:(CAShapeLayer *)barPathLayer
{
    if (self.animationDuration == 0.0)
        return;
    
    [barPathLayer removeAllAnimations];
    
    CABasicAnimation *pathAnimation	= [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    pathAnimation.fromValue			= [NSNumber numberWithFloat:0.0f];
    pathAnimation.toValue			= [NSNumber numberWithFloat:0.4f];
    [barPathLayer addAnimation:pathAnimation forKey:@"strokeEnd"];
}

- (void)setupXAxisLabels
{
    //if (_xLabelView.alpha > 0.0) {
    _xLabelView.alpha = 0.0;
    [[_xLabelView subviews] makeObjectsPerformSelector:@selector(removeFromSuperview)];
    //}
    
    if (_barLabels.count == 0)
        return;
    
    //CGFloat barWidthRatio = 0;
    CGFloat	xPos = _barLayer.bounds.size.width / (_numberOfBars + 1);
    //CGFloat	xPos0 = xPos;
    
    //CGFloat xPosInit = xPos;
    CGFloat xPosLast = self.incrmtxposValue;
    for (NSInteger i = 0; i < _numberOfBars; i++) {
      xPosLast = xPos;
        
      NSString *xLabelText	= [_barLabels objectAtIndex:i];
      //CGSize xLabelSize = [xLabelText sizeWithFont:self.xLabelFont];
      CGSize xLabelSize = [xLabelText sizeWithAttributes:@{NSFontAttributeName: self.yLabelFont}];
      CGRect xLabelFrame		= CGRectMake(0.0,
                                             0.0,
                                             xLabelSize.width,
                                             xLabelSize.height);
      UILabel *xLabel			= [[UILabel alloc] initWithFrame:xLabelFrame];
      xLabel.font				= [UIFont fontWithName:@"Helvetica" size:10.0];
      xLabel.backgroundColor	= [UIColor clearColor];
      xLabel.textColor		= self.xLabelColor;
      xLabel.textAlignment	= NSTextAlignmentCenter; //NSTextAlignmentRight;
      xLabel.text				= xLabelText;
      xLabel.transform		= CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(-_xLabelRotation));
        
        // Position the label appropriately
      switch (self.xLabelType) {
        case GraphViewXLabelTypeVerticle:
          default:
            xLabel.center = CGPointMake(xPos, (xLabelSize.width / 2.0));
            break;
                
        case GraphViewXLabelTypeHorizontal:
            xLabel.center = CGPointMake(xPos, _xLabelMaxHeight / 2.0);
            break;
                
        case GraphViewXLabelTypeAngled: {
            CGFloat labelHeightWithAngle	= sin(DEGREES_TO_RADIANS(_xLabelRotation)) * xLabelSize.width;
            xLabel.center					= CGPointMake(xPos - (labelHeightWithAngle / 2.0), labelHeightWithAngle / 2.0);
            break;
        }
      }
      [_xLabelView addSubview:xLabel];
        
    }
}

- (void) displayAxisLabels
{
    //if (self.hasYLabels || _barTexts.count > 0 || _barLabels.count > 0)	{
        if (self.animationDuration > 0.0) {
            __weak UICurveView *weakSelf = self;
            [UIView animateWithDuration:self.animationDuration / 2.0 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
                _yLabelView.alpha	= 1.0;
                _xLabelView.alpha	= 1.0;
                _barTextView.alpha	= 1.0;
            } completion:^(BOOL finished) {
                if (weakSelf.delegate && [weakSelf.delegate respondsToSelector:@selector(animationDidEndForBarChart:)])
                    [weakSelf.delegate animationDidEndForBarChart:weakSelf];
            }];
        }
        else {
            _yLabelView.alpha	= 1.0;
            _xLabelView.alpha	= 1.0;
            _barTextView.alpha	= 1.0;
            
            if (_delegate && [_delegate respondsToSelector:@selector(animationDidEndForBarChart:)])
                [_delegate animationDidEndForBarChart:self];
        }
    /*}
    else {
        if (_delegate && [_delegate respondsToSelector:@selector(animationDidEndForBarChart:)])
            [_delegate animationDidEndForBarChart:self];
    }*/
}

- (int) getHrateRngIdx:(short)nHrate
{
    int nIdx = 0;
    if(_bHorBar)
        return nIdx;
    if(_numberOfBars == 0)
        _numberOfBars = _nBarCount;
    
    //float fDelta = (_yMaxLine - _yMinLine) / _numberOfBars;
    float fDelta = (_fFitHRMax - _fMinHRVal) / _numberOfBars;
  
  
    float fRng0 = _yMinLine - 0.5;// - fDelta;
    float fRng1 = _yMinLine + fDelta * 1;
    float fRng2 = _yMinLine + fDelta * 2;
    float fRng3 = _yMinLine + fDelta * 3;
    float fRng4 = _yMinLine + fDelta * 4;
    
    if(nHrate < fRng0)
        nIdx = 1;
    else if(nHrate >= fRng0 && nHrate < fRng1)
        nIdx = 1;
    else if(nHrate >= fRng1 && nHrate < fRng2)
        nIdx = 2;
    else if(nHrate >= fRng2 && nHrate < fRng3)
        nIdx = 3;
    else if(nHrate >= fRng3 && nHrate < fRng4)
        nIdx = 4;
    else if(nHrate >= fRng4)
        nIdx = 5;
    
    _nCurtColorIdx = nIdx;
    
    return nIdx;
}


- (void) setTimeRngDur:(int)nIdx dur:(CGFloat)fSecDur
{
  if(_bBigScreen) { //_bIpad
     AppDelegate* pApp = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    _sTimeDur[nIdx] = [pApp getHourMinSec:fSecDur];
    
  }
  else {
    //CGFloat fDurMinute = fSecDur * _afPointCoef[nIdx] / 60.0;
    CGFloat fDurMinute = fSecDur / 60.0;
    if(fDurMinute >= 100)
      _sTimeDur[nIdx] = [NSString stringWithFormat:@"%.0f", fDurMinute];
    else if(fDurMinute >= 10)
      _sTimeDur[nIdx] = [NSString stringWithFormat:@"%.1f", fDurMinute];
    else
      _sTimeDur[nIdx] = [NSString stringWithFormat:@"%.2f", fDurMinute];
  }
}

- (void) resetData
{
  _bMovrCurve = NO;
  _nMoveCurveTick = 0;
  [self.values removeAllObjects];
  if(_bHorBar)
    [self setNeedsDisplay];
  else
    [self reloadData];
}

- (void)hideHgtBar:(BOOL)bHide;
{
  _bResetData = bHide;
  [self reloadData];
}

@end
